package lol.clann.minecraft.springboot.api.context;

import com.ruoshui.utils.java.stack.StackTraceManager;
import lol.clann.minecraft.springboot.SpringBootPlugin;
import lol.clann.minecraft.springboot.api.model.core.Plugin;
import lol.clann.minecraft.springboot.api.spi.plugin.PluginDefine;
import lol.clann.minecraft.springboot.remap.context.RemapContext;
import lombok.extern.slf4j.Slf4j;
import org.bukkit.Bukkit;

import java.util.*;

/**
 *
 * @author pyz
 * @date 2019/5/2 3:10 PM
 */
@Slf4j
public class PluginContext {
    /**
     * key: className
     * value: plugin
     */
    private static final Map<String, Plugin> classPluginMap = new HashMap<>();
    /**
     * key: pluginId
     * value: plugin
     */
    private static final Map<String, Plugin> pluginMap = new HashMap<>();
    private static boolean resolved = false;

    public static void resolvePlugins() throws Exception {
        if (resolved) {
            return;
        }
        resolved = true;
        for (PluginDefine pluginDefine : ServiceLoader.load(PluginDefine.class)) {
            Set<String> depends = pluginDefine.getPluginDepends();
            if (depends != null) {
                for (String depend : depends) {
                    org.bukkit.plugin.Plugin plugin = Bukkit.getPluginManager().getPlugin(depend);
                    if (plugin == null) {
                        LOGGER.warn("plugin {} depend on {}. But {} not exist.", pluginDefine.getId(), depend, depend);
                    }
                }
            }
            Plugin plugin = Plugin.from(pluginDefine, pluginMap);
//            配置项目包路径
            for (String basePackages : plugin.getBasePackages()) {
                StackTraceManager.getInstance().getPackagePrefixs().add(basePackages);
            }
            for (String className : plugin.getClasses()) {
//                注册后,类加载时才能被remap
                RemapContext.registerRemapClasses(className);
                classPluginMap.put(className, plugin);
            }
            LOGGER.info("detect springboot plugin id={} name={} jarFile={}", plugin.getId(), plugin.getDisplayName(), plugin.getFile().toFile().getName());
        }
    }

    public static Plugin getPlugin(String id) {
        return pluginMap.get(id);
    }

    public static Plugin getSBPPlugin() {
        return pluginMap.get(SpringBootPlugin.id);
    }

    public static Plugin getPluginByClass(Class clazz) {
        return classPluginMap.get(clazz.getName());
    }

    public static Plugin getPluginByClass(String className) {
        return classPluginMap.get(className);
    }

    public static Collection<Plugin> getPlugins() {
        return pluginMap.values();
    }
}
